package com.aries.crossgate.common.support.shiro;


import com.aries.crossgate.common.utils.Constant;
import com.aries.crossgate.common.utils.ShiroUtils;
import com.aries.crossgate.common.utils.SpringContextUtils;
import com.aries.crossgate.modules.sys.dao.SysUserDao;
import com.aries.crossgate.modules.sys.dao.SysUserTokenDao;
import com.aries.crossgate.modules.sys.entity.SysUser;
import com.aries.crossgate.modules.sys.service.SysMenuService;
import com.aries.crossgate.modules.sys.service.SysUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Set;


/**
 * @author fh
 *  2015-3-6
 */
public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private SysUserDao sysUserDao;
    
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysUserTokenDao sysUserTokenDao;

    /**
     * 认证信息.(身份验证)
     * Authentication 是用来验证用户身份
     * @param token
                * @return
     * @throws AuthenticationException
                */
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String userName = (String) token.getPrincipal();
            String passWord = new String((char[]) token.getCredentials());
            SysUser sysUser = sysUserDao.selectByUserName(userName);
               if(sysUser==null){
                throw new UnknownAccountException("账号或密码不正确");
            }
            // 密码错误
            if (!passWord.equals(sysUser.getPassWord())) {
                throw new IncorrectCredentialsException("账号或密码不正确");
            }

            // 账号锁定
            if (sysUser.getStatus() == 0) {
                throw new LockedAccountException("账号已被锁定,请联系管理员");
            }
            //用户存入session
            ShiroUtils.setSessionAttribute(Constant.SYSUSER,sysUser);
            ShiroUtils.setSessionAttribute(Constant.SYSUSERID,sysUser.getUserId());

            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(sysUser, passWord, getName());
            return info;
    }

    /**
     * 此方法调用  hasRole,hasPermission的时候才会进行回调.
     *
     * 权限信息.(授权):
     * 1、如果用户正常退出，缓存自动清空；
     * 2、如果用户非正常退出，缓存自动清空；
     * 3、如果我们修改了用户的权限，而用户不退出系统，修改的权限无法立即生效。
     * （需要手动编程进行实现；放在service进行调用）
     * 在权限修改后调用realm中的方法，realm已经由spring管理，所以从spring中获取realm实例，
     * 调用clearCached方法；
     * :Authorization 是授权访问控制，用于对用户进行的操作授权，证明该用户是否允许进行当前操作，如访问某个链接，某个资源文件等。
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        /*SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        Long userId = Long.valueOf(ShiroUtils.getUserId());
        //用户角色
        Set<String> rolesSet = sysUserService.listUserRoles(userId);
        //用户权限
        Set<String> permsSet = sysUserService.listUserPerms(userId);
        authorizationInfo.setRoles(rolesSet);
        authorizationInfo.setStringPermissions(permsSet);
        return authorizationInfo;*/
        Object next = principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = null;
        if(next instanceof SysUser) { // 避免授权报错
            String userId = ShiroUtils.getUserId();
            SysMenuService menuService = SpringContextUtils.getBean(SysMenuService.class);
            Set<String> permsSet = menuService.listPerms(userId);
            info = new SimpleAuthorizationInfo();
            info.setStringPermissions(permsSet);
        }
        return info;
    }

}
